package com.hmall.user.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hmall.common.exception.BadRequestException;
import com.hmall.common.utils.BeanUtils;
import com.hmall.common.utils.CollUtils;
import com.hmall.common.utils.UserContext;
import com.hmall.user.domain.dto.AddressDTO;
import com.hmall.user.domain.po.Address;
import com.hmall.user.service.IAddressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.models.Swagger;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.swing.*;
import java.util.Collections;
import java.util.List;

/**
 * 收货地址管理控制器
 * 处理与用户收货地址相关的HTTP请求
 */
@RestController // 来源：Spring MVC    作用：标记该类为 RESTful 风格的控制器，等价于@Controller + @ResponseBody  示例效果：所有方法返回值会自动序列化为 JSON 响应
@RequestMapping("/addresses") // 来源：Spring MVC  作用：指定该控制器的基础请求路径    示例效果：该类下的接口路径都会以/addresses开头
@RequiredArgsConstructor // 来源：Lombok   作用：自动生成必需参数的构造函数（针对final字段）
@Api(tags = "收货地址管理接口") // 来源：Swagger（Springfox）    作用：为 Swagger 文档添加分组标签   文档效果：在 API 文档中显示为 "收货地址管理接口" 组
public class AddressController {

    // 注入收货地址服务
    private final IAddressService addressService;

    /**
     * 根据地址ID查询收货地址
     * @param id 地址ID
     * @return 地址详情DTO
     */
    @ApiOperation("根据id查询地址")
    // 来源：Spring MVC    作用：映射 HTTP GET 请求，等价于@RequestMapping(method = RequestMethod.GET)    路径参数：{addressId}表示路径变量，对应方法参数中的@PathVariable
    @GetMapping("{addressId}")
    // @ApiParam("地址id")    来源：Swagger  作用：为 API 参数添加描述信息   文档效果：在 Swagger UI 中显示参数说明
    // @PathVariable("addressId")   来源：Spring MVC   作用：绑定路径变量到方法参数  示例映射：请求路径/addresses/123 → id = 123
    public AddressDTO findAddressById(@ApiParam("地址id") @PathVariable("addressId") Long id) {

        // 1. 通过地址ID去地址表address查询地址信息
        Address address = addressService.getById(id);

        // 2. 校验地址归属（确保当前用户只能访问自己的地址）
        // 通过UserContext.getUser()获取用户 ID 而非直接使用address.getUserId()，主要是出于权限校验和安全隔离的考虑。具体原因如下：
        // [1]核心目的：验证资源归属 [2]业务需求：用户只能访问自己的收货地址，不能访问他人的地址。
        Long currentUserId = UserContext.getUser();

        if (!address.getUserId().equals(currentUserId)) {
            throw new BadRequestException("该地址不属于当前登录用户");
        }

        // 3. 将PO对象转换为DTO对象返回
        return BeanUtils.copyBean(address, AddressDTO.class);
    }

    /**
     * 查询当前用户的所有收货地址
     * @return 地址列表DTO
     */
    @ApiOperation("查询当前用户地址列表")
    @GetMapping
    public List<AddressDTO> findMyAddresses() {

        // 1. 构建查询条件，查询address表中userId字段值等于UserContext.getUser()的数据行
        QueryWrapper<Address> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", UserContext.getUser());

        // 2. 查询当前用户的所有地址
        List<Address> addressList = addressService.list(queryWrapper);

        // 3. 处理空结果
        if (CollUtils.isEmpty(addressList)) {
            return Collections.emptyList();
        }

        // 4. 将PO列表转换为DTO列表
        return BeanUtils.copyList(addressList, AddressDTO.class);
    }
}
